package ge.scenes;

 

import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * 
 * @author Abel
 *	A Track of a scene has a list of clues frames who activated
 *	when the time of that frames is reached.
 */
public abstract class Track 
{

	protected ArrayList<Frame> clueFrames;
	protected int  actualFrame;
	
	public Track()
	{

		clueFrames =   new ArrayList<Frame>();
		actualFrame = -1;
	}
	
	
	/**
	 * 	Update is called just after change the frame, 
	 * in both ways.
	 */
	protected void update(double time)
	{
		
	}
	/**
	 * 	Advances the pointer of the track the quantity of time indicate.
	 *  It will execute the new clue frames reached.
	 * @param time Time to advance
	 */
	public void advance(double time)
	{
		 
		if(actualFrame < clueFrames.size()-1)
		{
			if(time > clueFrames.get(actualFrame+1).getTime() )
			{
				
				actualFrame++;
				
				reachFrame(clueFrames.get(actualFrame));
			}
		}
		update(time);
	}
	/**
	 * 	Reverses the pointer of the track the quantity of time indicate.
	 *  It will execute the new clue frames reached.
	 * @param time Time to advance
	 */
	public void reverse(double time)
	{
		 
		if(actualFrame > 0)
		{
			Frame f = clueFrames.get(actualFrame-1);
			if(time < f.getTime())
			{
				actualFrame--;
				reachReverseFrame(f);
			}
		}
		update(time);
	}
	
	public int getIndexOfFrameBefore(double time)
	{
		int i;
		//We will situate at the frame just before reach the times
		for(i = 0; i < clueFrames.size(); i++)
		{
			 if(clueFrames.get(i).getTime() > time)
				 break;
		}
		return --i;
	}
	
	
	/**
	 * 	Remove the frame with that time.
	 * 
	 * 	Add frame is not a Track function, it will depend
	 *  directly from the kind of track you are using.
	 * @param time
	 */
	public void remove(double time )
	{
		clueFrames.remove(new Frame(time));
		 
	}

	/**
	 * 	Executes the concrete frame
	 * @param f frame reached
	 */
	protected abstract void reachFrame(Frame f);
	/**
	 * Executes the concrete frame
	 * @param f Frame reached going at the opposite direction
	 */
	protected abstract void reachReverseFrame(Frame f);
	/**
	 * /**
	 * That function is called when setCurrentTime of 
	 * scene it's executed. The track has to know where it is
	 * and what to do (may depending on the direction).
	 * @param time new time 
	 * @param advance direction (true it's forward, false backward)
	 */
	protected abstract void currentTimeJump(double time, boolean advance);
	
	
}
